home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-05-19 | 16.0 KB | 395 lines | [TEXT/Pyth] |
- #
- # Class for printing reports on profiled python code. rev 1.0 4/1/94
- #
- # Based on prior profile module by Sjoerd Mullender...
- # which was hacked somewhat by: Guido van Rossum
- #
- # see jprofile.doc and jprofile.py for more info.
-
- # Copyright 1994, by InfoSeek Corporation, all rights reserved.
- # Written by James Roskind
- #
- # Permission to use, copy, modify, and distribute this Python software
- # and its associated documentation for any purpose (subject to the
- # restriction in the following sentence) without fee is hereby granted,
- # provided that the above copyright notice appears in all copies, and
- # that both that copyright notice and this permission notice appear in
- # supporting documentation, and that the name of InfoSeek not be used in
- # advertising or publicity pertaining to distribution of the software
- # without specific, written prior permission. This permission is
- # explicitly restricted to the copying and modification of the software
- # to remain in Python, compiled Python, or other languages (such as C)
- # wherein the modified or derived code is exclusively imported into a
- # Python module.
- #
- # INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- # SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- # FITNESS. IN NO EVENT SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY
- # SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- # RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
- import os
- import time
- import string
- import marshal
- import regex
-
- #**************************************************************************
- # Class Stats documentation
- #**************************************************************************
- # This class is used for creating reports from data generated by the
- # Profile class. It is a "friend" of that class, and imports data either
- # by direct access to members of Profile class, or by reading in a dictionary
- # that was emitted (via marshal) from the Profile class.
- #
- # The big change from the previous Profiler (in terms of raw functionality)
- # is that an "add()" method has been provided to combine Stats from
- # several distinct profile runs. Both the constructor and the add()
- # method now take arbitrarilly many file names as arguments.
- #
- # All the print methods now take an argument that indicats how many lines
- # to print. If the arg is a floating point number between 0 and 1.0, then
- # it is taken as a decimal percentage of the availabel lines to be printed
- # (e.g., .1 means print 10% of all available lines). If it is an integer,
- # it is taken to mean the number of lines of data that you wish to have
- # printed.
- #
- # The sort_stats() method now processes some additionaly options (i.e., in
- # addition to the old -1, 0, 1, or 2). It takes an arbitrary number of quoted
- # strings to select the sort order. For example sort_stats('time', 'name')
- # sorts on the major key of "internal function time", and on the minor
- # key of 'the name of the function'. Look at the two tables in sort_stats()
- # and get_sort_arg_defs(self) for more examples.
- #
- # All methods now return "self", so you can string together commands like:
- # Stats('foo', 'goo').strip_dirs().sort_stats('calls').\
- # print_stats(5).print_callers(5)
- #
- #**************************************************************************
- import fpformat
-
- class Stats:
- def __init__(self, *args):
- if not len(args):
- arg = None
- else:
- arg = args[0]
- args = args[1:]
- self.init(arg)
- apply(self.add, args).ignore()
-
- def init(self, arg):
- self.all_callees = None # calc only if needed
- self.files = []
- self.fcn_list = None
- self.total_tt = 0
- self.total_calls = 0
- self.prim_calls = 0
- self.max_name_len = 0
- self.top_level = {}
- self.stats = {}
- self.sort_arg_dict = {}
- self.load_stats(arg)
- trouble = 1
- try:
- self.get_top_level_stats()
- trouble = 0
- finally:
- if trouble:
- print "Invalid timing data",
- if self.files: print self.files[-1],
- print
-
-
- def load_stats(self, arg):
- if not arg: self.stats = {}
- elif type(arg) == type(""):
- f = open(arg, 'r')
- self.stats = marshal.load(f)
- f.close()
- try:
- file_stats = os.stat(arg)
- arg = time.ctime(file_stats[8]) + " " + arg
- except: # in case this is not unix
- pass
- self.files = [ arg ]
- elif hasattr(arg, 'create_stats'):
- arg.create_stats()
- self.stats = arg.stats
- arg.stats = {}
- if not self.stats:
- raise TypeError, "Cannot create or construct a " \
- + `self.__class__` \
- + " object from '" + `arg` + "'"
- return
-
- def get_top_level_stats(self):
- for func in self.stats.keys():
- cc, nc, tt, ct, callers = self.stats[func]
- self.total_calls = self.total_calls + nc
- self.prim_calls = self.prim_calls + cc
- self.total_tt = self.total_tt + tt
- if callers.has_key(("jprofile", 0, "profiler")):
- self.top_level[func] = None
- if len(func_std_string(func)) > self.max_name_len:
- self.max_name_len = len(func_std_string(func))
-
- def add(self, *arg_list):
- if not arg_list: return self
- if len(arg_list) > 1: apply(self.add, arg_list[1:])
- other = arg_list[0]
- if type(self) != type(other) or \
- self.__class__ != other.__class__:
- other = Stats(other)
- self.files = self.files + other.files
- self.total_calls = self.total_calls + other.total_calls
- self.prim_calls = self.prim_calls + other.prim_calls
- self.total_tt = self.total_tt + other.total_tt
- for func in other.top_level.keys():
- self.top_level[func] = None
-
- if self.max_name_len < other.max_name_len:
- self.max_name_len = other.max_name_len
-
- self.fcn_list = None
-
- for func in other.stats.keys():
- if self.stats.has_key(func):
- old_func_stat = self.stats[func]
- else:
- old_func_stat = (0, 0, 0, 0, {},)
- self.stats[func] = add_func_stats(old_func_stat, \
- other.stats[func])
- return self
-
-
-
- # list the tuple indicies and directions for sorting,
- # along with some printable description
- sort_arg_dict_default